package com.yunao.service.impl;

import java.util.Arrays;
import java.util.Map;
import java.util.Map.Entry;

import com.yunao.commons.serachcore.core.Isearch;
import com.yunao.commons.serachcore.core.IsearchFactory;
import com.yunao.commons.serachcore.core.bean.*;
import com.yunao.commons.serachcore.core.exception.SearchException;
import com.yunao.commons.serachcore.core.help.GroupField;
import com.yunao.commons.serachcore.core.help.Sort;
import com.yunao.commons.serachcore.core.query.Query;
import com.yunao.commons.serachcore.core.query.QueryBuilder;
import com.yunao.commons.utils.DomainSourceUtils;
import com.yunao.service.IsearchService;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.stereotype.Service;


@Service("isearchService")
public class IsearchServiceImpl implements IsearchService {

	Isearch isearch;

	public IsearchServiceImpl() {
		isearch = IsearchFactory.getIsearchCache();
//		isearch = IsearchFactory.getIsearch();
	}

	@Override
	public Articles distinct(Map<String, String> params) {
		try {
			Query query = parseParams(params);
			return isearch.distinct(query);
		} catch (SearchException e) {
			throw new IllegalArgumentException(e);
		}
	}
	
	@Override
	public Articles query(Map<String, String> params) {
		try {
			Query query = parseParams(params);
			return isearch.query(query);
		} catch (SearchException e) {
			throw new IllegalArgumentException(e);
		}
	}

	@Override
	public Groups group(Map<String, String> params) {
		try {
			Query query = parseParams(params);
			return isearch.group(query);
		} catch (SearchException e) {
			throw new IllegalArgumentException(e);
		}
	}

	@Override
	public Cubes cube(Map<String, String> params) {
		try {
			Query query = parseParams(params);
			return isearch.cube(query);
		} catch (SearchException e) {
			throw new IllegalArgumentException(e);
		}
	}

	@Override
	public Wordclouds wordcloud(Map<String, String> params) {
		try {
			Query query = parseParams(params);
			return isearch.wordcloud(query);
		} catch (SearchException e) {
			throw new IllegalArgumentException(e);
		}
	}

	@Override
	public Wordrelations wordrelation(Map<String, String> params) {
		try {
			Query query = parseParams(params);
			return isearch.wordrelation(query);
		} catch (SearchException e) {
			throw new IllegalArgumentException(e);
		}
	}

	@Override
	public Clusters cluster(Map<String, String> params) {
		try {
			Query query = parseParams(params);
			return isearch.cluster(query);
		} catch (SearchException e) {
			throw new IllegalArgumentException(e);
		}
	}

	private Query parseParams(Map<String, String> params) {
		QueryBuilder builder = QueryBuilder.create();
		for (Entry<String, String> entry : params.entrySet()) {
			String value = entry.getValue();
			if (value.isEmpty())
				continue;

			switch (entry.getKey()) {
			case "sort":
				builder.sort(Sort.valueOf(value.toUpperCase()));
				break;
			case "id":
				long[] ids = split(value);
				if (ids.length > 0) {
					builder.id(ids);
					builder.nonTrimArticle();
				}
				break;
			case "keywords":
				builder.keywords(value);
				break;
			case "title":
				builder.title(value);
				break;
			case "offset":
				builder.offset(NumberUtils.toInt(value));
				break;
			case "limit":
				builder.limit(NumberUtils.toInt(value));
				break;
			case "author":
				builder.author(StringUtils.split(value, ","));
				break;
			case "domain":
				String[] domains = StringUtils.split(value, ",");
				String[] ds = ArrayUtils.EMPTY_STRING_ARRAY;
				for (String domain : domains) {
					String[] ds2 = DomainSourceUtils.getDomain(domain);
					if (ds2.length == 0) {
						ds = ArrayUtils.add(ds, domain);
					} else {
						ds = ArrayUtils.addAll(ds, ds2);
					}
				}
				if (ds.length > 0) {
					builder.domain(ds);
				}
				break;
			case "host":
				builder.host(StringUtils.split(value, ","));
				break;
			case "media_type":
				String[] mediaTypes = StringUtils.split(value, ",");
				if (mediaTypes.length > 0)
					builder.mediaType(mediaTypes);
				break;
			case "message_type":
				String[] messageTypes = StringUtils.split(value, ",");
				if (messageTypes.length > 0)
					builder.messageType(messageTypes);
				break;
			case "channel":
				String[] channels = StringUtils.split(value, ",");
				if (channels.length > 0)
					builder.channel(channels);
				break;
			case "emotion":
				String[] emotions = StringUtils.split(value, ",");
				if (emotions.length > 0)
					builder.emotion(emotions);
				break;
			case "domain_level":
				String[] domainLevels = StringUtils.split(value, ",");
				if (domainLevels.length > 0)
					builder.domainLevel(domainLevels);
				break;
			case "location":
				String[] locations = StringUtils.split(value, ",");
				if (locations.length > 0)
					builder.location(locations);
				break;
			case "domestic":
				int domestic = NumberUtils.toInt(value);
				if (domestic == 1)
					builder.isDomestic();
				if (domestic == 2)
					builder.isOverseas();
				break;
			case "trim_article":
				boolean flag = BooleanUtils.toBoolean(value);
				if (flag) 
					builder.trimArticle();
				else
					builder.nonTrimArticle();
				break;

			default:
				break;
			}
		}

		if (params.containsKey("greaterequal")) {
			long t = Long.parseLong(params.get("greaterequal"));
			builder.timeGreaterThanOrEqualTo(t);
		} else if (params.containsKey("greaterthan")) {
			long t = Long.parseLong(params.get("greaterthan"));
			builder.timeGreaterThan(t);
		} else if (params.containsKey("between")) {
			long[] t = split(params.get("between"));
			builder.timeBetween(t[0], t[1]);
		} else if (params.containsKey("days")){
			builder.timeGreaterThanOrEqualTo(Integer.valueOf(params.get("days")));
		}else if(params.containsKey("id")){

		}else {
			builder.timeGreaterThanOrEqualTo(30);
		}

		if (params.containsKey("group2")) {
			builder.cube(GroupField.valueOf(params.get("group").toUpperCase()),
					GroupField.valueOf(params.get("group2").toUpperCase()));
		} else if (params.containsKey("group")) {
			builder.group(GroupField.valueOf(params.get("group").toUpperCase()));
		}

		if (params.containsKey("max_word")) {
			int maxWord = NumberUtils.toInt(params.get("max_word"), 200);
			builder.wordcloud(maxWord);
			if (params.containsKey("stop_words")) {
				String[] stopWords = StringUtils.split(params.get("stop_words"));
				if (stopWords.length > 0)
					builder.wordrelation(stopWords);
			}
		}

		if (params.containsKey("distance") || params.containsKey("max_group")) {
			double distance = NumberUtils.toDouble(params.get("distance"), 0.5);
			int maxGroup = NumberUtils.toInt(params.get("max_group"), 20);
			builder.cluster(distance, maxGroup);
		}

		return builder.build();
	}

	private long[] split(String v) {
		String[] array = StringUtils.split(v, ",");
		return Arrays.stream(array).map(String::trim).filter(StringUtils::isNotEmpty).mapToLong(Long::parseLong)
				.toArray();
	}

}
